package com.shop.cereshop.commons.service.im;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSONObject;
import com.shop.cereshop.commons.config.TXCOSConfig;
import com.shop.cereshop.commons.domain.express.HttpResult;
import com.shop.cereshop.commons.domain.im.tx.req.ImBaseModel;
import com.shop.cereshop.commons.domain.im.tx.req.enums.ReqUrlEnums;
import com.shop.cereshop.commons.domain.im.tx.req.follow.*;
import com.shop.cereshop.commons.domain.im.tx.req.friend.FriendBaseReq;
import com.shop.cereshop.commons.domain.im.tx.req.friend.FriendItem;
import com.shop.cereshop.commons.domain.im.tx.req.friend.GetFriendListReq;
import com.shop.cereshop.commons.domain.im.tx.req.friend.GetSpecifyFriendReq;
import com.shop.cereshop.commons.domain.im.tx.req.msg.MsgInfoReq;
import com.shop.cereshop.commons.domain.im.tx.req.msg.ModifyC2CMsgReq;
import com.shop.cereshop.commons.domain.im.tx.req.msg.ModifyGroupMsgReq;
import com.shop.cereshop.commons.domain.im.tx.req.push.PushInfo;
import com.shop.cereshop.commons.domain.im.tx.req.user.*;
import com.shop.cereshop.commons.domain.im.tx.resp.ImBaseResp;
import com.shop.cereshop.commons.domain.im.tx.resp.follow.FollowGetInfoResp;
import com.shop.cereshop.commons.domain.im.tx.resp.follow.FollowGetResp;
import com.shop.cereshop.commons.domain.im.tx.resp.follow.FollowUserResp;
import com.shop.cereshop.commons.domain.im.tx.resp.follow.GetSpecifyFriendResp;
import com.shop.cereshop.commons.domain.im.tx.resp.friend.FriendBaseResp;
import com.shop.cereshop.commons.domain.im.tx.resp.speaking.QueryUserSpeakingResp;
import com.shop.cereshop.commons.domain.im.tx.resp.user.ImUserBaseResp;
import com.shop.cereshop.commons.domain.im.tx.req.ocr.BizLicenseOCRReq;
import com.shop.cereshop.commons.domain.im.tx.resp.ocr.BizLicenseOCRResp;
import com.shop.cereshop.commons.service.ocr.TencentOCRService;
import com.shop.cereshop.commons.utils.HttpUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import sun.misc.BASE64Encoder;

import javax.annotation.Resource;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.util.Random;
import java.util.Collections;

import com.shop.cereshop.commons.domain.im.tx.req.recentcontact.CreateContactGroupReq;

@Slf4j
@Service("ImUserService")
public class ImUserService {
    @Resource
    private ImBaseModel imBaseModel;


    private static final String HMAC_ALGORITHM = "HmacSHA1"; //签名算法
    private static final String CONTENT_CHARSET = "UTF-8";
    @Resource
    private TXCOSConfig tencentCOSConfig;

    @Resource
    private TencentOCRService tencentOCRService;

    /**
     * 获取签名
     */
    public String getUploadSignature() throws Exception {
        String strSign = "";
        String contextStr = "";
        // 生成原始参数字符串
        long currentTime = System.currentTimeMillis() / 1000;
        long signValidDuration = 3600 * 24 * 2;
        long endTime = (currentTime + signValidDuration);
        contextStr += "secretId=" + java.net.URLEncoder.encode(tencentCOSConfig.getSecretId(), "utf8");
        contextStr += "&currentTimeStamp=" + currentTime;
        contextStr += "&expireTime=" + endTime;
        contextStr += "&random=" + new Random().nextInt(java.lang.Integer.MAX_VALUE);
        try {
            Mac mac = Mac.getInstance(HMAC_ALGORITHM);
            SecretKeySpec secretKey = new SecretKeySpec(tencentCOSConfig.getSecretKey().getBytes(CONTENT_CHARSET), mac.getAlgorithm());
            mac.init(secretKey);
            byte[] hash = mac.doFinal(contextStr.getBytes(CONTENT_CHARSET));
            byte[] sigBuf = byteMerger(hash, contextStr.getBytes("utf8"));
            strSign = base64Encode(sigBuf);
            strSign = strSign.replace(" ", "").replace("\n", "").replace("\r", "");
        } catch (Exception e) {
            throw e;
        }
        return strSign;
    }

    /**
     * 导入单个账号
     */
    public ImUserBaseResp accountImport(AccountImportReq accountImportReq) {
        imBaseModel.setReqMethod(ReqUrlEnums.ACCOUNT_IMPORT.getUrl());
        HttpResult result = HttpUtils.doPostJson(imBaseModel.toString(), accountImportReq);
        log.info("导入单个账号 accountImport result:{}", result);
        if (result.getStatus() == 200) {
            return JSONObject.parseObject(result.getBody(), ImUserBaseResp.class);
        } else {
            return ImUserBaseResp.builder().actionStatus("FAIL").errorCode(-1).build();
        }
    }

    @Async
    public void accountImportAsync(AccountImportReq accountImportReq) {
        try {
            accountImport(accountImportReq);
        } catch (Exception e) {
            log.error("异步导入IM账号失败", e);
        }
    }



    /**
     * 查询账号
     */
    public ImUserBaseResp accountCheck(CheckItemReq checkItemReq) {
        imBaseModel.setReqMethod(ReqUrlEnums.ACCOUNT_CHECK.getUrl());
        HttpResult result = HttpUtils.doPostJson(imBaseModel.toString(), JSONObject.toJSON(checkItemReq));
        log.info("accountCheck result:{}", result);
        if (result.getStatus() == 200) {
            return JSONObject.parseObject(result.getBody(), ImUserBaseResp.class);
        } else {
            return ImUserBaseResp.builder().actionStatus("FAIL").errorCode(-1).build();
        }
    }

    /**
     * 导入多个账号
     */
    public ImUserBaseResp multiAccountImport(AccountListImportReq accountListImportReq) {
        imBaseModel.setReqUrl(ReqUrlEnums.BASE_URL.getUrl());
        imBaseModel.setReqMethod(ReqUrlEnums.MULTIACCOUNT_IMPORT.getUrl());
        HttpResult result = HttpUtils.doPostJson(imBaseModel.toString(), accountListImportReq);
        if (result.getStatus() == 200) {
            return JSONObject.parseObject(result.getBody(), ImUserBaseResp.class);
        } else {
            return ImUserBaseResp.builder().actionStatus("FAIL").errorCode(-1).build();
        }
    }

    /**
     * 删除账号
     */
    public ImUserBaseResp accountDelete(DeleteItemReq deleteItemReq) {
        imBaseModel.setReqMethod(ReqUrlEnums.ACCOUNT_DELETE.getUrl());
        HttpResult result = HttpUtils.doPostJson(imBaseModel.toString(), JSONObject.toJSON(deleteItemReq));
        if (result.getStatus() == 200) {
            return JSONObject.parseObject(result.getBody(), ImUserBaseResp.class);
        } else {
            return ImUserBaseResp.builder().actionStatus("FAIL").errorCode(-1).build();
        }
    }

    /**
     * 添加好友
     */
    public FriendBaseResp friendAdd(FriendBaseReq req) {
        imBaseModel.setReqMethod(ReqUrlEnums.FRIEND_ADD.getUrl());
        HttpResult result = HttpUtils.doPostJson(imBaseModel.toString(), JSONObject.toJSON(req));
        if (result.getStatus() == 200) {
            return JSONObject.parseObject(result.getBody(), new com.alibaba.fastjson.TypeReference<FriendBaseResp<FriendItem>>() {
            }.getType());
        } else {
            FriendBaseResp<Object> objectFriendBaseResp = new FriendBaseResp<>();
            objectFriendBaseResp.setActionStatus("FAIL");
            objectFriendBaseResp.setErrorCode(-1);
            return objectFriendBaseResp;
        }
    }

    /**
     * 拉取好友
     */
    public FriendBaseResp<FriendItem> getFriendList(GetFriendListReq req) {
        imBaseModel.setReqMethod(ReqUrlEnums.FRIEND_GET.getUrl());
        HttpResult result = HttpUtils.doPostJson(imBaseModel.toString(), JSONObject.toJSON(req));
        if (result.getStatus() == 200) {
            return JSONObject.parseObject(result.getBody(), new com.alibaba.fastjson.TypeReference<FriendBaseResp<FriendItem>>() {
            }.getType());
        } else {
            FriendBaseResp<FriendItem> objectFriendBaseResp = new FriendBaseResp<>();
            objectFriendBaseResp.setActionStatus("FAIL");
            objectFriendBaseResp.setErrorCode(-1);
            return objectFriendBaseResp;
        }
    }

    /**
     * 拉取指定好友
     */
    public GetSpecifyFriendResp getSpecifyFriend(GetSpecifyFriendReq req) {
        imBaseModel.setReqMethod(ReqUrlEnums.FRIEND_GET_LIST.getUrl());
        HttpResult result = HttpUtils.doPostJson(imBaseModel.toString(), JSONObject.toJSON(req));
        if (result.getStatus() == 200) {
            return JSONObject.parseObject(result.getBody(), GetSpecifyFriendResp.class);
        } else {
            GetSpecifyFriendResp objectFriendBaseResp = new GetSpecifyFriendResp();
            objectFriendBaseResp.setActionStatus("FAIL");
            objectFriendBaseResp.setErrorCode(-1);
            return objectFriendBaseResp;
        }
    }

    /**
     * 发送消息
     */
    public FriendBaseResp sendMsg(MsgInfoReq req) {
        imBaseModel.setReqMethod(ReqUrlEnums.SINGLE_SEND_MSG.getUrl());
        //获取当前秒级时间戳
        req.setMsgRandom((int) DateUtil.currentSeconds());
        HttpResult result = HttpUtils.doPostJson(imBaseModel.toString(), JSONObject.toJSON(req));
        if (result.getStatus() == 200) {
            return JSONObject.parseObject(result.getBody(), FriendBaseResp.class);
        } else {
            FriendBaseResp objectFriendBaseResp = new FriendBaseResp<>();
            objectFriendBaseResp.setActionStatus("FAIL");
            objectFriendBaseResp.setErrorCode(-1);
            return objectFriendBaseResp;
        }
    }

    /**
     * 设置全局禁言
     */
    public ImBaseResp setGlobalBan(SetGlobalBanReq req) {
        imBaseModel.setReqMethod(ReqUrlEnums.SET_GLOBAL_BAN.getUrl());
        //获取当前秒级时间戳
        HttpResult result = HttpUtils.doPostJson(imBaseModel.toString(), JSONObject.toJSON(req));
        if (result.getStatus() == 200) {
            return JSONObject.parseObject(result.getBody(), ImBaseResp.class);
        } else {
            ImBaseResp objectFriendBaseResp = new ImBaseResp<>();
            objectFriendBaseResp.setActionStatus("FAIL");
            objectFriendBaseResp.setErrorCode(-1);
            return objectFriendBaseResp;
        }

    }

    /**
     * 查询全员禁言状态
     *
     * @param getAccount 查询禁言信息的账号
     */
    public QueryUserSpeakingResp getNoSpeaking(String getAccount) {
        imBaseModel.setReqMethod(ReqUrlEnums.GET_USER_SPEAKING.getUrl());
        //获取当前秒级时间戳
        JSONObject req = new JSONObject();
        req.put("Get_Account", getAccount);
        HttpResult result = HttpUtils.doPostJson(imBaseModel.toString(), req);
        if (result.getStatus() == 200) {
            return JSONObject.parseObject(result.getBody(), QueryUserSpeakingResp.class);
        } else {
            QueryUserSpeakingResp objectFriendBaseResp = new QueryUserSpeakingResp();
            objectFriendBaseResp.setActionStatus("FAIL");
            objectFriendBaseResp.setErrorCode(-1);
            return objectFriendBaseResp;
        }
    }

    /**
     * 推送全员、支持全部推送和根据标签推送
     */
    public ImBaseResp pushAllInfo(PushInfo req) {
        imBaseModel.setReqMethod(ReqUrlEnums.PUSH_MSG.getUrl());
        //获取当前秒级时间戳
        HttpResult result = HttpUtils.doPostJson(imBaseModel.toString(), JSONObject.toJSON(req));
        if (result.getStatus() == 200) {
            return JSONObject.parseObject(result.getBody(), ImBaseResp.class);
        } else {
            ImBaseResp objectFriendBaseResp = new ImBaseResp<>();
            objectFriendBaseResp.setActionStatus("FAIL");
            objectFriendBaseResp.setErrorCode(-1);
            return objectFriendBaseResp;
        }
    }

    /**
     * 单发推送 推送到指定账户 支持推送多个账户
     */
    public ImBaseResp pushBatch(PushInfo req) {
        imBaseModel.setReqMethod(ReqUrlEnums.PUSH_BATCH_MSG.getUrl());
        //获取当前秒级时间戳
        HttpResult result = HttpUtils.doPostJson(imBaseModel.toString(), JSONObject.toJSON(req));
        if (result.getStatus() == 200) {
            return JSONObject.parseObject(result.getBody(), ImBaseResp.class);
        } else {
            ImBaseResp objectFriendBaseResp = new ImBaseResp<>();
            objectFriendBaseResp.setActionStatus("FAIL");
            objectFriendBaseResp.setErrorCode(-1);
            return objectFriendBaseResp;
        }
    }

    /**
     * 关注用户
     */
    public FollowUserResp followAdd(FollowAddReq req) {
        imBaseModel.setReqMethod(ReqUrlEnums.FOLLOW_ADD.getUrl());
        //获取当前秒级时间戳
        HttpResult result = HttpUtils.doPostJson(imBaseModel.toString(), JSONObject.toJSON(req));
        if (result.getStatus() == 200) {
            return JSONObject.parseObject(result.getBody(), FollowUserResp.class);
        } else {
            FollowUserResp objectFriendBaseResp = new FollowUserResp();
            objectFriendBaseResp.setActionStatus("FAIL");
            objectFriendBaseResp.setErrorCode(-1);
            return objectFriendBaseResp;
        }
    }

    /**
     * 取消关注用户
     */
    public FollowUserResp followDelete(FollowDeleteReq req) {
        imBaseModel.setReqMethod(ReqUrlEnums.FOLLOW_DELETE.getUrl());
        //获取当前秒级时间戳
        HttpResult result = HttpUtils.doPostJson(imBaseModel.toString(), JSONObject.toJSON(req));
        if (result.getStatus() == 200) {
            return JSONObject.parseObject(result.getBody(), FollowUserResp.class);
        } else {
            FollowUserResp objectFriendBaseResp = new FollowUserResp();
            objectFriendBaseResp.setActionStatus("FAIL");
            objectFriendBaseResp.setErrorCode(-1);
            return objectFriendBaseResp;
        }
    }

    /**
     * 拉取关注、粉丝与互关列表
     */
    public FollowGetResp getFollowList(FollowGetReq req) {
        imBaseModel.setReqMethod(ReqUrlEnums.FOLLOW_GET.getUrl());
        //获取当前秒级时间戳
        HttpResult result = HttpUtils.doPostJson(imBaseModel.toString(), JSONObject.toJSON(req));
        if (result.getStatus() == 200) {
            return JSONObject.parseObject(result.getBody(), FollowGetResp.class);
        } else {
            FollowGetResp objectFriendBaseResp = new FollowGetResp();
            objectFriendBaseResp.setActionStatus("FAIL");
            objectFriendBaseResp.setErrorCode(-1);
            return objectFriendBaseResp;
        }
    }

    /**
     * 检查关注关系
     */
    public FollowUserResp followCheck(FollowCheckReq req) {
        imBaseModel.setReqMethod(ReqUrlEnums.FOLLOW_CHECK.getUrl());
        //获取当前秒级时间戳
        HttpResult result = HttpUtils.doPostJson(imBaseModel.toString(), JSONObject.toJSON(req));
        if (result.getStatus() == 200) {
            return JSONObject.parseObject(result.getBody(), FollowUserResp.class);
        } else {
            FollowUserResp objectFriendBaseResp = new FollowUserResp();
            objectFriendBaseResp.setActionStatus("FAIL");
            objectFriendBaseResp.setErrorCode(-1);
            return objectFriendBaseResp;
        }
    }

    /**
     * 获取用户的关注、粉丝与互关数
     */
    public FollowGetInfoResp getFollowInfo(FollowGetInfoReq req) {
        imBaseModel.setReqMethod(ReqUrlEnums.FOLLOW_GET_INFO.getUrl());
        //获取当前秒级时间戳
        HttpResult result = HttpUtils.doPostJson(imBaseModel.toString(), JSONObject.toJSON(req));
        if (result.getStatus() == 200) {
            return JSONObject.parseObject(result.getBody(), FollowGetInfoResp.class);
        } else {
            FollowGetInfoResp objectFriendBaseResp = new FollowGetInfoResp();
            objectFriendBaseResp.setActionStatus("FAIL");
            objectFriendBaseResp.setErrorCode(-1);
            return objectFriendBaseResp;
        }
    }


    /**** 内部方法***/
    public static byte[] byteMerger(byte[] byte1, byte[] byte2) {
        byte[] byte3 = new byte[byte1.length + byte2.length];
        System.arraycopy(byte1, 0, byte3, 0, byte1.length);
        System.arraycopy(byte2, 0, byte3, byte1.length, byte2.length);
        return byte3;
    }

    private String base64Encode(byte[] buffer) {
        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(buffer);
    }

    /**
     * 营业执照识别
     * 通过图片URL识别营业执照信息
     *
     * @param imageUrl 营业执照图片URL
     * @return 营业执照识别结果
     */
    public BizLicenseOCRResp recognizeBizLicense(String imageUrl) {
        log.info("开始识别营业执照，图片URL: {}", imageUrl);
        return tencentOCRService.bizLicenseOCRByUrl(imageUrl);
    }

    /**
     * 营业执照识别
     * 通过图片Base64编码识别营业执照信息
     *
     * @param imageBase64 营业执照图片Base64编码
     * @return 营业执照识别结果
     */
    public BizLicenseOCRResp recognizeBizLicenseByBase64(String imageBase64) {
        log.info("开始识别营业执照，使用Base64编码");
        return tencentOCRService.bizLicenseOCRByBase64(imageBase64);
    }

    /**
     * 营业执照识别
     * 使用完整参数进行营业执照识别
     *
     * @param req 营业执照识别请求参数
     * @return 营业执照识别结果
     */
    public BizLicenseOCRResp recognizeBizLicense(BizLicenseOCRReq req) {
        log.info("开始识别营业执照，使用完整参数");
        return tencentOCRService.bizLicenseOCR(req);
    }

    /**
     * 修改单聊历史消息
     * 文档: https://cloud.tencent.com/document/product/269/74740
     */
    public ImBaseResp modifyC2CMsg(ModifyC2CMsgReq req) {
        imBaseModel.setReqMethod(ReqUrlEnums.MODIFY_C2C_MSG.getUrl());
        HttpResult result = HttpUtils.doPostJson(imBaseModel.toString(), JSONObject.toJSON(req));
        if (result.getStatus() == 200) {
            return JSONObject.parseObject(result.getBody(), ImBaseResp.class);
        } else {
            ImBaseResp resp = new ImBaseResp();
            resp.setActionStatus("FAIL");
            resp.setErrorCode(-1);
            return resp;
        }
    }

    /**
     * 修改群聊历史消息
     * 文档: https://cloud.tencent.com/document/product/269/74741
     */
    public ImBaseResp modifyGroupMsg(ModifyGroupMsgReq req) {
        imBaseModel.setReqMethod(ReqUrlEnums.MODIFY_GROUP_MSG.getUrl());
        HttpResult result = HttpUtils.doPostJson(imBaseModel.toString(), JSONObject.toJSON(req));
        if (result.getStatus() == 200) {
            return JSONObject.parseObject(result.getBody(), ImBaseResp.class);
        } else {
            ImBaseResp resp = new ImBaseResp();
            resp.setActionStatus("FAIL");
            resp.setErrorCode(-1);
            return resp;
        }
    }

    /**
     * 创建会话分组数据
     * 文档: https://cloud.tencent.com/document/product/269/85791
     */
    public ImBaseResp createContactGroup(String fromAccount, String groupName, Integer type, String toAccount, String toGroupId) {
        imBaseModel.setReqUrl(ReqUrlEnums.BASE_URL.getUrl());
        imBaseModel.setReqMethod(ReqUrlEnums.CREATE_CONTACT_GROUP.getUrl());

        CreateContactGroupReq.ContactItem contactItem = new CreateContactGroupReq.ContactItem();
        contactItem.setType(type);
        contactItem.setTo_Account(toAccount);
        contactItem.setToGroupId(toGroupId);

        CreateContactGroupReq.GroupContactItem groupContactItem = new CreateContactGroupReq.GroupContactItem();
        groupContactItem.setGroupName(groupName);
        groupContactItem.setContactItem(Collections.singletonList(contactItem));

        CreateContactGroupReq req = new CreateContactGroupReq();
        req.setFrom_Account(fromAccount);
        req.setGroupContactItem(Collections.singletonList(groupContactItem));

        HttpResult result = HttpUtils.doPostJson(imBaseModel.toString(), JSONObject.toJSON(req));
        if (result.getStatus() == 200) {
            return JSONObject.parseObject(result.getBody(), ImBaseResp.class);
        } else {
            ImBaseResp resp = new ImBaseResp();
            resp.setActionStatus("FAIL");
            resp.setErrorCode(-1);
            return resp;
        }
    }
}
